package com.yzjs.localhost.service;


import com.yzjs.common.util.conversion.JsonUtil;
import com.yzjs.localhost.dictionaries.DealDictionary;
import com.yzjs.localhost.dictionaries.NeusoftDataStatus;
import com.yzjs.localhost.dictionaries.ResourceDictionary;
import com.yzjs.localhost.dto.ComparisonResultDTO;
import com.yzjs.localhost.dto.DataBundlingDTO;
import com.yzjs.localhost.dto.UserRightsDTO;
import com.yzjs.localhost.entity.sysUser.SysUserEntity;
import com.yzjs.localhost.entity.tDataLog.TDataLogEntity;
import com.yzjs.localhost.entity.tDataPersistenceAfter.TDataPersistenceAfterEntity;
import com.yzjs.localhost.entity.tDataPersistenceBeforce.TDataPersistenceBeforceEntity;
import com.yzjs.localhost.entity.tNeusoftComplianceTesting.TNeusoftComplianceTestingEntity;
import com.yzjs.localhost.entity.tNeusoftSysMenu.TNeusoftSysMenuEntity;
import com.yzjs.localhost.entity.tNeusoftSysRole.TNeusoftSysRoleEntity;
import com.yzjs.localhost.entity.tNeusoftSysRoleMenu.TNeusoftSysRoleMenuEntity;
import com.yzjs.localhost.entity.tNeusoftUniformityTesting.TNeusoftUniformityTestingEntity;
import com.yzjs.localhost.service.analysis.UserAnalysisService;
import com.yzjs.localhost.service.hrmAssessment.HrmAssessmentService;
import com.yzjs.localhost.service.hrmCertificate.HrmCertificateService;
import com.yzjs.localhost.service.hrmContract.HrmContractService;
import com.yzjs.localhost.service.hrmEducationInfo.HrmEducationInfoService;
import com.yzjs.localhost.service.hrmFamilyMembers.HrmFamilyMembersService;
import com.yzjs.localhost.service.hrmPositionChange.HrmPositionChangeService;
import com.yzjs.localhost.service.hrmPositionalTitles.HrmPositionalTitlesService;
import com.yzjs.localhost.service.hrmProfessionalQualification.HrmProfessionalQualificationService;
import com.yzjs.localhost.service.hrmRecruitment.HrmRecruitmentService;
import com.yzjs.localhost.service.hrmRsLeave.HrmRsLeaveService;
import com.yzjs.localhost.service.hrmUser.HrmUserService;
import com.yzjs.localhost.service.sysDept.SysDeptService;
import com.yzjs.localhost.service.sysMenu.SysMenuService;
import com.yzjs.localhost.service.hrmAwardSanction.HrmAwardSanctionService;
import com.yzjs.localhost.service.hrmFamilyMembers.HrmFamilyMembersService;
import com.yzjs.localhost.service.hrmProfessionalQualification.HrmProfessionalQualificationService;
import com.yzjs.localhost.service.hrmScientific.HrmScientificService;
import com.yzjs.localhost.service.hrmTitleChange.HrmTitleChangeService;
import com.yzjs.localhost.service.sysLogininfor.SysLogininforService;
import com.yzjs.localhost.service.sysRole.SysRoleService;
import com.yzjs.localhost.service.sysUser.SysUserService;
import com.yzjs.localhost.service.tDataLog.TDataLogService;
import com.yzjs.localhost.service.tDataPersistenceAfter.TDataPersistenceAfterService;
import com.yzjs.localhost.service.tDataPersistenceBeforce.TDataPersistenceBeforceService;
import com.yzjs.localhost.service.tNeusoftComplianceTesting.TNeusoftComplianceTestingService;
import com.yzjs.localhost.service.tNeusoftSysMenu.TNeusoftSysMenuService;
import com.yzjs.localhost.service.tNeusoftSysRole.TNeusoftSysRoleService;
import com.yzjs.localhost.service.tNeusoftSysUser.TNeusoftSysUserService;
import com.yzjs.localhost.service.tNeusoftUniformityTesting.TNeusoftUniformityTestingService;
import io.swagger.annotations.ApiModelProperty;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;


import java.time.ZoneId;
import java.util.*;


import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 定时任务解析类别数据
 */
@Service("analysisService")
public class AnalysisService {

    @Autowired
    private TDataPersistenceBeforceService dataPersistenceBeforceService ;

    @Autowired
    private TDataPersistenceAfterService  dataPersistenceAfterService ;

    @Autowired
    private UserAnalysisService userAnalysisService;


    @Autowired
    private TNeusoftComplianceTestingService   neusoftComplianceTestingService;

    @Autowired
    private TNeusoftUniformityTestingService  neusoftUniformityTestingService ;

    @Autowired
    private TNeusoftSysMenuService neusoftSysMenuService;

    @Autowired
    private TNeusoftSysRoleService neusoftSysRoleService;

    @Autowired
    private TDataLogService  dataLogService;

    @Autowired
    private SysUserService sysUserService;


    @Autowired
    private SysRoleService sysRoleService;

    @Autowired
    private HrmEducationInfoService hrmEducationInfoService;

    @Autowired

    private SysDeptService sysDeptService ;

    @Autowired
    private SysMenuService  sysMenuService;


    @Autowired
    private HrmTitleChangeService hrmTitleChangeService;

    @Autowired
    private HrmFamilyMembersService hrmFamilyMembersService;

    @Autowired
    private HrmAssessmentService hrmAssessmentService;

    @Autowired
    private HrmCertificateService hrmCertificateService;

    @Autowired
    private HrmRecruitmentService hrmRecruitmentService;

    @Autowired
    private HrmUserService hrmUserService;

    @Autowired
    private HrmAwardSanctionService  hrmAwardSanctionService ;

    @Autowired
    private HrmScientificService hrmScientificService;

    @Autowired
    private HrmProfessionalQualificationService hrmProfessionalQualificationService ;

    @Autowired
    private TruthCheckingAbilityService truthCheckingAbilityService ;

    @Autowired
    private HrmContractService hrmContractService;

    @Autowired
    private HrmPositionalTitlesService hrmPositionalTitlesCompliance;

    @Autowired
    private HrmPositionChangeService hrmPositionChangeCompliance;

    @Autowired
    private HrmRsLeaveService hrmRsLeaveService;




    // 角色缓存信息
    public static Map<String,String> roleMap ;

    // 菜单缓存信息
    public static Map<String,String> menusMap ;

    // 字典信息项
    public static Map<String,String> translationMap ;




    /**
     * 用户权限数据数据解析入口程序
     */
    @Scheduled(cron = "0 */1 * * * *")
    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
    public void userRightsAnalysis(){
        /**
         *  1. 获取所有未解析数据入库前推送列表，时间倒序
         *  2. 获取所有未解析入库后推送列表数据，时间倒序
         *  3. 将【入库前】，【入库后的数据】进行一一配对绑定
         *  4. 获取所有用户菜单权限，角色权限。
         *  5. 对数据进行一致性检测，合规性检测比对程序
         *  6. 判断数据是否为【用户，角色，菜单，部门】,是：保存更新数据，并且更新本地缓存表
         *  否 将解析规则数据保存本地，并将风险数据保存到【一致性检测结果表】【合规性检测结果表】
         *
         * */
        TDataPersistenceBeforceEntity  beforce = new TDataPersistenceBeforceEntity();
        beforce.setDealSign(DealDictionary.UNTREATED);
        List<TDataPersistenceBeforceEntity> beforces = dataPersistenceBeforceService.findList(beforce);

        TDataPersistenceAfterEntity   after  = new TDataPersistenceAfterEntity();
        after.setDealSign(DealDictionary.UNTREATED);
        List<TDataPersistenceAfterEntity> afters = dataPersistenceAfterService.findList(after);


        TDataLogEntity dataLogQuery  = new TDataLogEntity();
        dataLogQuery.setDealSign(DealDictionary.UNTREATED);
        List<TDataLogEntity>    logs = dataLogService.findList(dataLogQuery);

        // 进行比对碰撞
        List<DataBundlingDTO>  dtos =  new LinkedList<DataBundlingDTO>();
        for (TDataPersistenceBeforceEntity beforceEntity :beforces){
            for (TDataPersistenceAfterEntity afterEntity:afters ){
                if (beforceEntity.getDataIdentification().equals(afterEntity.getDataIdentification())&&
                        beforceEntity.getDataResources().equals(afterEntity.getDataResources()) ){
                    DataBundlingDTO  dto  = new DataBundlingDTO();
                    dto.setDataIdentification(beforceEntity.getDataIdentification());
                    dto.setDataResources(beforceEntity.getDataResources());
                    dto.setBeforce(beforceEntity);
                    dto.setAfter(afterEntity);
                    dtos.add(dto);
                    break;
                }
            }
        }

        for (DataBundlingDTO dto :dtos){
            for(TDataLogEntity log:logs){
                if (dto.getBeforce().getDataIdentification().equals(log.getDataIdentification()) ){
                    dto.setDataLog(log);
                }
            }
        }


        // 加载一次东软用户权限信息
        Map<Long, UserRightsDTO> userLoad= userAnalysisService.LoadUserPower();
        InitMenus();
        InitRoles();
        // 循环进入比对分析
        for (DataBundlingDTO dto :dtos){
            // 合规性以及一致性校验,主要校验权限这一块信息记录
            ComplianceAndUniformityTesting(userLoad,dto);
        }
    }


    /**
     * 1.识别数据资源类型，获取资源进行数据分析
     * 2.获取数据信息,操作人信息，进行权限校验
     *
     * @param userLoad  用户权限信息
     * @param dto       解析识别实体
     */
    @SneakyThrows
    public void ComplianceAndUniformityTesting(Map<Long, UserRightsDTO> userLoad, DataBundlingDTO dto){
        TDataPersistenceBeforceEntity beforce =dto.getBeforce();
        String info  = beforce.getInfo();
        Map<String,Object>  beforceParse = JsonUtil.json2map(info);
        Long userId = Long.valueOf(beforce.getOperatorId());
        UserRightsDTO  rights =  userLoad.get(userId);
        // 合规性校验
        ComplianceVerification(rights,beforce);
        //一致性校验信息
        TDataPersistenceAfterEntity after =dto.getAfter();

        ComparisonResultDTO resultDTO = null ;
        // switch case为自定义解析一块函数
        switch (dto.getBeforce().getDataResources()){
            case ResourceDictionary.SYS_USER:
                resultDTO = sysUserService.UserCompliance(dto,rights);
                break;
            case ResourceDictionary.SYS_ROLE:
                resultDTO = sysRoleService.RoleCompliance(dto,rights);
                break;
            case ResourceDictionary.SYS_DEPT :
                resultDTO = sysDeptService.DeptCompliance(dto,rights)  ;
                break;
            case ResourceDictionary.HRM_EDUCATION_INFO:
                resultDTO = hrmEducationInfoService.hrmEducationInfoCompliance(dto,rights);
                break;
            case  ResourceDictionary.SYS_MENU:
                resultDTO = sysMenuService.MenuCompliance(dto,rights);
                break;
            case ResourceDictionary.HRM_AWARD_SANCTION:
                resultDTO = hrmAwardSanctionService.AwardSanctionCompliance(dto, rights);
                break;
            case ResourceDictionary.HRM_FAMILY_MEMBERS:
                resultDTO = hrmFamilyMembersService.hrmFamilyMembersCompliance(dto, rights);
                break;
            case ResourceDictionary.HRM_PROFESSIONAL_QUALIFICATION:
                resultDTO = hrmProfessionalQualificationService.hrmProfessionalQualificationCompliance(dto, rights);
                break;
            case ResourceDictionary.HRM_TITLE_CHANGE:
                resultDTO = hrmTitleChangeService.TitleChangeCompliance(dto, rights);
                break;
            case ResourceDictionary.HRM_SCIENTIFIC:
                resultDTO = hrmScientificService.ScientificCompliance(dto, rights);
                break;
            case ResourceDictionary.HRM_ASSESSMENT:
                resultDTO=hrmAssessmentService.AssessmentCompliance(dto,rights);
                break;
            case ResourceDictionary.HRM_CERTIFICATE:;
                resultDTO=hrmCertificateService.CertificateCompliance(dto,rights);
                break;
           case ResourceDictionary.HRM_USER:
               resultDTO=hrmUserService.HrmUserCompliance(dto,rights);
               break;
           case ResourceDictionary.HRM_RECRUITMENT:
                resultDTO=hrmRecruitmentService.HrmRecruitmentCompliance(dto,rights);
                break;
           case ResourceDictionary.HRM_CONTRACT:
               resultDTO=hrmContractService.hrmContractCompliance(dto,rights);
               break;
           case ResourceDictionary.HRM_POSITIONAL_TITLES:
               resultDTO=hrmPositionalTitlesCompliance.hrmPositionalTitlesCompliance(dto,rights);
               break;
           case ResourceDictionary.HRM_POSITION_CHANGE:
               resultDTO=hrmPositionChangeCompliance.hrmPositionChangeCompliance(dto,rights);
               break;
           case ResourceDictionary.HRM_RS_LEAVE:
               resultDTO=hrmRsLeaveService.hrmRsLeaveCompliance(dto,rights);
               break;

        }
        // 对接大数据中心信息比对
        truthCheckingAbilityService.VerificationAbilityIdNumber(dto,rights);

        // 并且匹配相应的操作日志信息
        if (dto.getDataLog() == null  ){
            resultDTO = new ComparisonResultDTO();
            if(dto.getDataLog() != null && !dto.getDataLog().getInfo().contains("200")){
                resultDTO.setAbstractName("操作日志记录行为：失败");
                resultDTO.setWarningInfo("获取操作日志日志中没有记录成功操作信息如下：" +JsonUtil.obj2json(dto.getDataLog() ));
            }else{
                resultDTO.setAbstractName("操作日志不存在");
                resultDTO.setWarningInfo("没有获取到对应的操作日志信息结果");
            }
            resultDTO.setMathFlag(false);

        }



        // 判断是否需要写入预警信息不一致结果表
        if ( resultDTO != null &&  !resultDTO.isMathFlag()){
            uniformityTestingInsert(resultDTO.getAbstractName(),resultDTO.getWarningInfo(),beforce,rights);
        }
        if (dto.getDataLog() != null){
            dto.getDataLog().setDealSign(DealDictionary.PROCESSED);
            dataLogService.update(dto.getDataLog());
        }
        beforce.setDealSign(DealDictionary.PROCESSED);
        dataPersistenceBeforceService.update(beforce);

        after.setDealSign(DealDictionary.PROCESSED);
        dataPersistenceAfterService.update(after);
    }

    /**
     * 初始化菜单基础信息
     * @return
     */
    public void InitMenus(){
        TNeusoftSysMenuEntity  menuEntity = new TNeusoftSysMenuEntity();
        menuEntity.setStatus(NeusoftDataStatus.DATA_NORMAL);
        menuEntity.setMenuType("F");
        List<TNeusoftSysMenuEntity> menus = neusoftSysMenuService.findList(menuEntity);

        Map<String,String> menusMap = menus.stream().filter(menu->StringUtils.isNotEmpty(menu.getPerms())).collect(Collectors.toMap(TNeusoftSysMenuEntity::getPerms, TNeusoftSysMenuEntity::getMenuName));
        this.menusMap = menusMap;
    }

    /**
     * 初始化角色信息
     * @return
     */
    public void InitRoles(){
        TNeusoftSysRoleEntity roleEntity = new TNeusoftSysRoleEntity();
        roleEntity.setStatus(NeusoftDataStatus.DATA_NORMAL);
        List<TNeusoftSysRoleEntity>  roleEntities = neusoftSysRoleService.findList(roleEntity);

        Map<String,String> roleMap = roleEntities.stream().collect(Collectors.toMap(TNeusoftSysRoleEntity::getRoleKey, TNeusoftSysRoleEntity::getRoleName));
       this.roleMap = roleMap;
    }



    /**
     *
     * @param beforceParse  入参之前解析
     * @param afterParse    入参之后解析
     * @return
     */
    public static ComparisonResultDTO comparisonMap(String operatorCode,Map<String,Object>  beforceParse , Map<String,Object>  afterParse, String comparisonKeys ){
        ComparisonResultDTO dto = new ComparisonResultDTO();
        String missMessage = "";
        String [] comparisonKeyArrays = comparisonKeys.split(",");
        for(int i=0;i<comparisonKeyArrays.length;i++){
            if (beforceParse.get(comparisonKeyArrays[i]) !=null &&  !beforceParse.get(comparisonKeyArrays[i]).equals(afterParse.get(comparisonKeyArrays[i])) ){
                missMessage += (translationMap.get(comparisonKeyArrays[i])==null?comparisonKeyArrays[i]:translationMap.get(comparisonKeyArrays[i])) +"不一致 ";
            }
        }
        // 比对核验预警
        if (missMessage.length() >1){
            dto.setMathFlag(false);
            dto.setWarningInfo(missMessage);
            dto.setAbstractName(menusMap.get(operatorCode)+"一致性校验报警");
        }
        return  dto;
    }

    /**
     * 保存一致性检测风险信息
     */
    public void uniformityTestingInsert(String abstractName,String warningInfo,
                                        TDataPersistenceBeforceEntity beforce,UserRightsDTO  rights){
        TNeusoftUniformityTestingEntity uniformityTesting  = new TNeusoftUniformityTestingEntity();
        uniformityTesting.setJurisdictionCode(beforce.getOperatorCode());
        uniformityTesting.setJurisdiction(menusMap.get(beforce.getOperatorCode()));
        uniformityTesting.setAbstractName(abstractName);
        uniformityTesting.setDataIdentification(beforce.getDataIdentification());
        uniformityTesting.setDisposalStatus(DealDictionary.UNTREATED);
        uniformityTesting.setWarningTime(new Date());

        uniformityTesting.setPushTime(Date.from( beforce.getCreateDate().atZone( ZoneId.systemDefault()).toInstant()));
        if(rights != null){
            uniformityTesting.setOperationId(rights.getUserId().intValue());
            uniformityTesting.setOperationName(rights.getNickName());
            uniformityTesting.setOperationRoleId(rights.getRoleId().intValue());
            uniformityTesting.setOperationRoleName(rights.getRoleName());
            uniformityTesting.setOperationDepartId(rights.getDeptId().intValue());
            uniformityTesting.setOperationDepartName(rights.getDeptName());
        }
        uniformityTesting.setResourceType(beforce.getDataResources());
        uniformityTesting.setResourceName(ResourceDictionary.conversionMap.get(beforce.getDataResources()));
        uniformityTesting.setWarningInfo(warningInfo);
        neusoftUniformityTestingService.insert(uniformityTesting);
    }

    /**
     * 合规性校验
     */
    public void ComplianceVerification( UserRightsDTO  rights,TDataPersistenceBeforceEntity beforce){
        String abstractName ="";
        String warningInfo ="";
        // 用户角色权限信息
        Map<String,TNeusoftSysMenuEntity>  roleMenus  = null ;
        // 角色权限信息
        Map<String, TNeusoftSysRoleEntity>  roles = null ;
        // 部门权限信息
        Map<String, TNeusoftSysMenuEntity>  deptMenus = null ;

        boolean flag = false;
        // 用户信息不存在
        if( rights == null){
            flag = true;
            abstractName="用户信息不存在";
            warningInfo="该操作用户不存在本地，无法找到对应权限";
        }else{
            // 超级管理员免权限校验
            if (rights.getNickName().equals("admin")){
                return;
            }
            deptMenus = rights.getDeptMenus();
            roleMenus = rights.getRoleMenus();
            roles = rights.getRoles();
            //  进行角色合规性校验
            if (StringUtils.isNotEmpty(beforce.getOperatorRoleCode())&&
                    ( rights.getRoles().get(beforce.getOperatorRoleCode()) == null)){
                flag = true;
                abstractName="操作角色编码未匹配";
                warningInfo="该操作所需要角色编码 "+beforce.getOperatorRoleCode()+"但是当前操作用户角色未存在匹配信息";
            }

            // 菜单合规性校验
            if (StringUtils.isNotEmpty(beforce.getOperatorCode())&&
                    (rights.getRoleMenus().get(beforce.getOperatorCode()) ==null&&
                            rights.getDeptMenus().get(beforce.getOperatorCode()) == null )){
                flag = true;
                abstractName="操作权限编码未匹配";
                warningInfo="该操作所需要权限编码 "+beforce.getOperatorCode()+"但是当前操作用户权限集合中未存在匹配信息";
            }
        }

        if (flag){
            TNeusoftComplianceTestingEntity complianceTesting = new TNeusoftComplianceTestingEntity();
            complianceTesting.setJurisdictionCode(beforce.getOperatorCode());
            complianceTesting.setJurisdiction(menusMap.get(beforce.getOperatorCode()));
            complianceTesting.setAbstractName(abstractName);
            complianceTesting.setDataIdentification(beforce.getDataIdentification());
            complianceTesting.setDisposalStatus(DealDictionary.UNTREATED);
            complianceTesting.setWarningTime(new Date());
            complianceTesting.setPushTime(Date.from( beforce.getCreateDate().atZone( ZoneId.systemDefault()).toInstant()) ) ;
            complianceTesting.setResourceType(beforce.getDataResources());
            complianceTesting.setResourceName(ResourceDictionary.conversionMap.get(beforce.getDataResources()));
            complianceTesting.setWarningInfo(warningInfo);

            if(rights != null){
                complianceTesting.setOperationId(rights.getUserId().intValue());
                complianceTesting.setOperationName(rights.getNickName());
                complianceTesting.setOperationRoleId(rights.getRoleId().intValue());
                complianceTesting.setOperationRoleName(rights.getRoleName());
                complianceTesting.setOperationDepartId(rights.getDeptId().intValue());
                complianceTesting.setOperationDepartName(rights.getDeptName());
            }
            complianceTesting.setRoleSnapshot(JsonUtil.mapToJsonIgnoreNull(roles));
            complianceTesting.setRolePermissionSnapshot(JsonUtil.mapToJsonIgnoreNull(roleMenus));
            complianceTesting.setDeptPermissionSnapshot(JsonUtil.mapToJsonIgnoreNull(deptMenus));
            neusoftComplianceTestingService.insert(complianceTesting);
        }

    }










}
